<?php

namespace hichefu;

use think\cache\driver\Redis;
use think\Exception;

/**
 * Api接口
 * 一、文档说明
 * 适用于飞侠平台代驾业务
 * 二、接口说明
 * 2.1 接口规范
 * 所有接口均为Https服务协议，使用Post方式请求，请求头:application/json。所有出入参数必须使用utf-8编码进行UrlEncode，并使用aesKey进行加密加密方式:AES加密
 **/
class Api
{

    // {"cipherParam":"加密数据","token":"","tranCode":""}
    protected $url;
    protected $api = [
        'getToken' => 'api/base/getToken',
        'updateOrderStatus' => 'api/order/updateOrderStatus',
        'updateDriverLocation' => 'api/order/updateDriverLocation',
        'submitOrderBill' => 'api/order/submitOrderBill',
        'getTotalFee' => 'api/order/getTotalFee',
    ];
    protected $apiVersion = '1.0.0';
    protected $appKey;
    protected $appSecret;

    public function __construct()
    {
        $config = config('driving.hichefu');
        $this->url = $config['url'];
        $this->appKey = $config['appKey'];
        $this->appSecret = $config['appSecret'];
    }

    /**
     * 3.1获取token
     *
     * @return string
     **/
    public function getToken()
    {
        $options = \think\Config::get('redis');
        $redis = new Redis($options);
        $key = $options['prefix'] . 'token';
        $access_token_result = $redis->get($key);
        if ($access_token_result) {
            return $access_token_result;
        }

        $api = $this->api[__FUNCTION__];
        $url = $this->url . $api;
        $params = [
            "tranCode" => $this->appKey,
        ];
        $form_data = http_build_query($params);//将数组转换为符合 form-data 格式的字符串

        $header = $this->header($api);

        $result = $this->request_post($url, $form_data, $header);
        $result = json_decode($result, true);
        if (isset($result['statusCode'])) {
            throw new Exception('【hichefu】statusCode:' . $result['statusCode'] . ',' . $result['messages']);
        }

        // {"code":200,"content":{"expireTime":1719982637909,"token":"200a1de8e625a2ae0f5c1a4534a55532"},"messages":"success"}
        $decrypt = $this->decrypt($result['cipherParam']);
        $decrypt = json_decode($decrypt, true);
        if (isset($decrypt['code']) && $decrypt['code'] != ErrorCode::$OK) {
            throw new Exception('【hichefu】code:' . $decrypt['code'] . ',' . $decrypt['messages']);
        }

        $redis->set($key, $decrypt['content']['token'], 7000);
        return $decrypt['content']['token'];
    }

    /**
     * 3.2 订单状态更新
     *
     * @param array $params
     * @return mixed
     **/
    public function updateOrderStatus($params)
    {
        return $this->request($params, __FUNCTION__);
    }

    /**
     * 3.3 司机位置更新
     * ⽀持批量更新，建议每30秒打包上传
     *
     * @param array $params
     * @return mixed
     **/
    public function updateDriverLocation($params)
    {
        return $this->request($params, __FUNCTION__);
    }

    /**
     * 3.4 ⾏程账单上报
     *
     * @param array $params
     * @return mixed
     **/
    public function submitOrderBill($params)
    {
        return $this->request($params, __FUNCTION__);
    }

    /**
     * 3.6 支付订单查询
     *
     * @param array $params
     * @return mixed
     **/
    public function getTotalFee($params)
    {
        return $this->request($params, __FUNCTION__);
    }

    /**
     * 封装Aes加密
     *
     * @param string $input
     * @return mixed
     **/
    public function encrypt($input)
    {
        $aes = new Aes();
        try {
            $encrypt = $aes->encrypt($input);
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        return $encrypt;
    }

    /**
     * 封装Aes解密
     *
     * @param string $input
     * @return mixed
     **/
    public function decrypt($input)
    {
        $aes = new Aes();
        try {
            $decrypt = $aes->decrypt($input);
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        return $decrypt;
    }

    /**
     * 封装通⽤返回参数
     * @param integer $code 业务错误代码
     * @param string $messages 错误描述
     * @param mixed $content 返回内容
     * @return mixed
     */
    public static function result($code, $messages = '', $content = [])
    {
        $result = [
            'code' => $code,
            'messages' => !empty($messages) ? $messages : ErrorCode::code_list()[$code],
            'content' => $content,
        ];
        return json_encode($result, JSON_UNESCAPED_UNICODE);
    }

    /**
     * 封装入参格式
     * @param string $cipherParam 加密参数
     * @param string $token token
     * @return mixed
     */
    public function input($cipherParam, $token = '')
    {
        $result = [
            'cipherParam' => $cipherParam,
            'token' => $token,
            'tranCode' => $this->appKey,
        ];
        return json_encode($result, JSON_UNESCAPED_UNICODE);
    }

    /**
     * 封装通⽤请求参数header
     *
     * @param string $api 接⼝具体api名称
     * @param string $token token
     * @return mixed
     **/
    public function header($api, $token = '')
    {
        $header = [
            'appId:' . '',
            'api:' . $api,
            'apiVersion:' . $this->apiVersion,
            'timestamp:' . time(),
            'appKey:' . $this->appKey,
            'sign:' . $this->appSecret,
            'token:' . $token,
        ];
        $header = [];
        if (!empty($token)) {
            $header = array_merge($header, ['Content-Type:application/json']);
        } else {
            $header = array_merge($header, ['Content-Type: application/x-www-form-urlencoded; charset=utf-8']);
        }
        return $header;
    }

    /**
     * 发送post请求
     * @param string $url
     * @param string $param
     * @param array $header
     * @return bool|mixed
     */
    public function request_post($url = '', $param = '', $header = [])
    {
        $ch = curl_init(); //初始化curl
        curl_setopt($ch, CURLOPT_URL, $url); //抓取指定网页
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);// 设置header
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_POST, true); //post提交方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
        $data = curl_exec($ch); //运行curl
        curl_close($ch);
        return $data;
    }

    /**
     * 组装请求信息
     *
     * @param array $params
     * @param string $function
     **/
    public function request($params, $function)
    {
        $token = $this->getToken();

        $api = $this->api[$function];
        $url = $this->url . $api;
        $json_params = json_encode($params);

        $encrypt = $this->encrypt($json_params);

        $input = $this->input($encrypt, $token);

        $header = $this->header($api, $token);

        $result = $this->request_post($url, $input, $header);
        $result = json_decode($result, true);
        if (isset($result['statusCode'])) {
            user_log('hichefu/' . $function, json_encode($params, JSON_UNESCAPED_UNICODE) . ' ' . $result);
            throw new Exception('【hichefu】statusCode:' . $result['statusCode'] . ',' . $result['messages']);
        }

        // {"code":200,"messages":"success"}
        $decrypt = $this->decrypt($result['cipherParam']);
        user_log('hichefu/' . $function, json_encode($params, JSON_UNESCAPED_UNICODE) . ' ' . $decrypt);
        $decrypt = json_decode($decrypt, true);
        if (isset($decrypt['code']) && $decrypt['code'] != ErrorCode::$OK) {
            throw new Exception('【hichefu】code:' . $decrypt['code'] . ',' . $decrypt['messages']);
        }
        return $decrypt;
    }

    /**
     * 订单状态
     **/
    const STAGE_1 = 1;
    const STAGE_2 = 2;
    const STAGE_3 = 3;
    const STAGE_11 = 11;
    const STAGE_12 = 12;
    const STAGE_13 = 13;
    const STAGE_14 = 14;
    const STAGE_15 = 15;
    const STATUS = [
        self::STAGE_1 => '已受理',
        self::STAGE_2 => '客户取消',
        self::STAGE_3 => '无人接单',
        self::STAGE_11 => '已接单',
        self::STAGE_12 => '已到达',
        self::STAGE_13 => '开始代驾',
        self::STAGE_14 => '结束代驾',
        self::STAGE_15 => '收费完成',
    ];
    const STATUS_LIST = [
        self::STAGE_1 => '已受理',
        self::STAGE_2 => '已取消', // 客户取消 无人接单
        self::STAGE_11 => '已接单', // 已接单 已到达
        self::STAGE_13 => '验车完成', // 开始代驾
        self::STAGE_15 => '交车完成', // 结束代驾 收费完成
    ];


    /**
     * 费⽤类型
     **/
    const COST_1 = 1;
    const COST_2 = 2;
    const COST_3 = 3;
    const COST_4 = 4;
    const COST_5 = 5;
    const COST_6 = 6;
    const COST_99 = 99;
    const COST = [
        self::COST_1 => '起步价',
        self::COST_2 => '里程费',
        self::COST_3 => '等候费',
        self::COST_4 => '远程费',
        self::COST_5 => '时长费',
        self::COST_6 => '调价补贴',
        self::COST_99 => '其他费用',
    ];

    /**
     * 服务类型
     **/
    const SERVICE_DRIVE = 'DRIVE';
    const SERVICE_TRANSFER = 'TRANSFER';
    const SERVICE = [
        self::SERVICE_DRIVE => '代驾',
        self::SERVICE_TRANSFER => '里取送车',
    ];

}
